use std::io::Write;

use git_transport::{client, client::TransportV2Ext};

use crate::fetch::{Arguments, Command};

impl Arguments {
    pub(crate) fn send<'a, T: client::Transport + 'a>(
        &mut self,
        transport: &'a mut T,
        add_done_argument: bool,
    ) -> Result<Box<dyn client::ExtendedBufRead + Unpin + 'a>, client::Error> {
        if self.haves.is_empty() {
            assert!(add_done_argument, "If there are no haves, is_done must be true.");
        }
        match self.version {
            git_transport::Protocol::V1 => {
                let (on_into_read, retained_state) = self.prepare_v1(
                    transport.connection_persists_across_multiple_requests(),
                    add_done_argument,
                )?;
                let mut line_writer =
                    transport.request(client::WriteMode::OneLfTerminatedLinePerWriteCall, on_into_read)?;
                let had_args = !self.args.is_empty();
                for arg in self.args.drain(..) {
                    line_writer.write_all(&arg)?;
                }
                if had_args {
                    line_writer.write_message(client::MessageKind::Flush)?;
                }
                for line in self.haves.drain(..) {
                    line_writer.write_all(&line)?;
                }
                if let Some(next_args) = retained_state {
                    self.args = next_args;
                }
                Ok(line_writer.into_read()?)
            }
            git_transport::Protocol::V2 => {
                let retained_state = self.args.clone();
                self.args.append(&mut self.haves);
                if add_done_argument {
                    self.args.push("done".into());
                }
                transport.invoke(
                    Command::Fetch.as_str(),
                    self.features.iter().filter(|(_, v)| v.is_some()).cloned(),
                    Some(std::mem::replace(&mut self.args, retained_state).into_iter()),
                )
            }
        }
    }
}
